package com.eye.catcher.service.generate.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eye.catcher.common.RedisUtils;
import com.eye.catcher.constants.RedisConstants;
import com.eye.catcher.constants.SbCode;
import com.eye.catcher.entity.TYwDaBaseInfo;
import com.eye.catcher.entity.TYwDaFieldInfo;
import com.eye.catcher.entity.TYwDaObserveInfo;
import com.eye.catcher.mapper.TYwDaObserveInfoMapper;
import com.eye.catcher.service.generate.ITYwDaBaseInfoService;
import com.eye.catcher.service.generate.ITYwDaFieldInfoService;
import com.eye.catcher.service.generate.ITYwDaObserveInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eye.catcher.system.role.param.RoleDto;
import com.eye.catcher.system.user.param.UserLoginInfo;
import com.eye.catcher.system.yw.Info.param.FieldInfoDto;
import com.eye.catcher.system.yw.Info.param.ObserveInfoDto;
import com.eye.catcher.system.yw.Info.param.ObserveInfoPage;
import com.eye.catcher.utils.DownloadUtils;
import com.eye.catcher.utils.UploadUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 观测信息表 服务实现类
 * </p>
 *
 * @author huzhiwei
 * @since 2022-05-12
 */
@Slf4j
@Service
public class TYwDaObserveInfoServiceImpl extends ServiceImpl<TYwDaObserveInfoMapper, TYwDaObserveInfo> implements ITYwDaObserveInfoService {
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private ITYwDaFieldInfoService fieldInfoService;
    @Autowired
    private ITYwDaBaseInfoService baseInfoService;

    @Value("${base.all-permissions.roleId}")
    private String baseAllPermissionsRoleId;

    @Value("${download.template.url-path}")
    private String downloadTemplateUrlPath;
    @Override
    public void addObserveInfo(TYwDaObserveInfo info) {
        UserLoginInfo userLoginInfo = (UserLoginInfo)redisUtils.get(RedisConstants.USER_INFO_EXPIRE.getKey()+info.getCreateUserId());
        info.setCreateUserId(info.getCreateUserId());
        info.setCreateUserName(userLoginInfo.getUserDto().getUserName());
        info.setCreateLoginName(userLoginInfo.getUserDto().getLoginName());
        info.setCreateTime(LocalDateTime.now());
        info.setSource(SbCode.DATA_SOURCE_CREATE.getCode());
        if(null != info.getFieldId()){
            TYwDaFieldInfo fieldInfo = fieldInfoService.getById(info.getFieldId());
            if(null != fieldInfo) {
                info.setFieldCode(fieldInfo.getFieldCode());
                info.setFieldName(fieldInfo.getFieldName());
                info.setBaseId(fieldInfo.getBaseId());
                info.setBaseCode(fieldInfo.getBaseCode());
                info.setBaseName(fieldInfo.getBaseName());
            }
        }
        this.save(info);
    }

    @Override
    public void editObserveInfo(TYwDaObserveInfo info) {
        UserLoginInfo userLoginInfo = (UserLoginInfo)redisUtils.get(RedisConstants.USER_INFO_EXPIRE.getKey()+info.getUpdateUserId());
        info.setUpdateUserId(info.getCreateUserId());
        info.setUpdateUserName(userLoginInfo.getUserDto().getUserName());
        info.setUpdateLoginName(userLoginInfo.getUserDto().getLoginName());
        info.setUpdateTime(LocalDateTime.now());
        if(null != info.getFieldId()){
            TYwDaFieldInfo fieldInfo = fieldInfoService.getById(info.getFieldId());
            if(null != fieldInfo) {
                info.setFieldCode(fieldInfo.getFieldCode());
                info.setFieldName(fieldInfo.getFieldName());
                info.setBaseId(fieldInfo.getBaseId());
                info.setBaseCode(fieldInfo.getBaseCode());
                info.setBaseName(fieldInfo.getBaseName());
            }
        }
        this.updateById(info);
    }


    @Override
    public String checkSameProportion(String baseId,String observeId,String sameProportion,String observeName) {
        QueryWrapper<TYwDaObserveInfo> wrapper = Wrappers.query();
        wrapper.eq("BASE_ID",baseId);//基地
        wrapper.eq("OBSERVE_NAME",observeName);//观测期
        List<TYwDaObserveInfo> list = this.list(wrapper);
//        int fourSum = 0;
        if(null != list){
            if(list.size() == 5){
                Double fourSum = list.stream()
                        .mapToDouble(observeInfo -> Double.parseDouble(observeInfo.getSameProportion()))
                        .sum();
                DecimalFormat doubleFormatter = new DecimalFormat("#.00");
                doubleFormatter.setRoundingMode(RoundingMode.HALF_UP);


//                if(StringUtils.isEmpty(observeId)){
//                    //查询最新的
////                    observeId
//                    QueryWrapper<TYwDaObserveInfo> wrapper1 = Wrappers.query();
//                    wrapper1.eq("BASE_ID",baseId);//基地
//                    wrapper1.eq("OBSERVE_NAME",observeName);//观测期
//                    wrapper1.orderByDesc(" CREATE_TIME ");
//                    List<TYwDaObserveInfo> list1 = this.list(wrapper1);
//                    observeId = String.valueOf(list1.get(0).getId());
//                }
//            }
//            if(list.size() == 5) {
                if (fourSum != 100) {
                    // ！= 100 标记
                    if(list.size() == 5){
                        TYwDaBaseInfo baseInfo = this.baseInfoService.getById(baseId);
                        if(null != baseInfo){
                            String sp = "";
                            if(StringUtils.isNotEmpty(baseInfo.getSameProportion())){
                                for(String str : baseInfo.getSameProportion().split(";")){
                                    if(str.indexOf(observeName) == -1){
                                        if(!"".equals(sp)){
                                            sp += ";";
                                        }
                                        sp += str;
                                    }
                                }
                            }
                            baseInfo.setSameProportion(
                                    (StringUtils.isEmpty(sp) ? "" : sp + ";") +
                                            observeName+"数据不合规，总占比: " + doubleFormatter.format(fourSum)
                            );
                            this.baseInfoService.updateById(baseInfo);
                        }
//                        TYwDaObserveInfo observeInfo = this.getById(observeId);
//                        if(null != observeInfo){
//                            TYwDaFieldInfo fieldInfo = this.fieldInfoService.getById(observeInfo.getFieldId());
//                            if(fieldInfo != null){
//                                String sp = "";
//                                if(StringUtils.isNotEmpty(fieldInfo.getSameProportion())){
//                                    for(String str : fieldInfo.getSameProportion().split(";")){
//                                        if(str.indexOf(observeInfo.getObserveName()) == -1){
//                                            if(!"".equals(sp)){
//                                                sp += ";";
//                                            }
//                                            sp += str;
//                                        }
//                                    }
//                                }
//                                fieldInfo.setSameProportion(
//                                        (StringUtils.isEmpty(sp) ? "" : sp + ";") +
//                                        observeInfo.getObserveName()+"数据不合规，总占比: " + fourSum
//                                );
//                                this.fieldInfoService.updateById(fieldInfo);
//                            }
//                        }
                    }
                }else{
                    // == 100 ，制空
                    if(list.size() == 5){
                        TYwDaBaseInfo baseInfo = this.baseInfoService.getById(baseId);
                        if(null != baseInfo) {
                            if(StringUtils.isNotEmpty(baseInfo.getSameProportion())){
                                String sp = "";
                                for(String str : baseInfo.getSameProportion().split(";")){
                                    if(str.indexOf(observeName) == -1){
                                        if(!"".equals(sp)){
                                            sp += ";";
                                        }
                                        sp += str;
                                    }
                                }

                                baseInfo.setSameProportion(sp);
                                this.baseInfoService.updateById(baseInfo);
                            }

                        }
//                        TYwDaObserveInfo observeInfo = this.getById(observeId);
//                        if(null != observeInfo){
//                            TYwDaFieldInfo fieldInfo = this.fieldInfoService.getById(observeInfo.getFieldId());
//                            if(fieldInfo != null){
//                                if(StringUtils.isNotEmpty(fieldInfo.getSameProportion())){
//                                    String sp = "";
//                                    for(String str : fieldInfo.getSameProportion().split(";")){
//                                        if(str.indexOf(observeInfo.getObserveName()) == -1){
//                                            if(!"".equals(sp)){
//                                                sp += ";";
//                                            }
//                                            sp += str;
//                                        }
//                                    }
//
//                                    fieldInfo.setSameProportion(sp);
//                                    this.fieldInfoService.updateById(fieldInfo);
//                                }
//                            }
//                        }
                    }
                }
            }
        }
        return null;
    }

    @Override
    public boolean isEmpty(TYwDaObserveInfo info) {
        QueryWrapper<TYwDaObserveInfo> wrapper = Wrappers.query();
        wrapper.eq("FIELD_ID",info.getFieldId());//田地
        wrapper.eq("OBSERVE_NAME",info.getObserveName());//观测期
        if( this.count(wrapper) > 0){
            return true;
        }
        return false;
    }

    @Override
    public void deleteByIds(String ids) {
        this.removeByIds(Arrays.asList(ids.split(",")));
    }

    @Override
    public Object getAllList(ObserveInfoDto observeInfo) {
        QueryWrapper<TYwDaObserveInfo> wrapper = Wrappers.query();
        //组装查询条件
        this.appendWrapper(wrapper,observeInfo);

        wrapper.orderByAsc(" BASE_ID,FIELD_ID,SORT_NO ");
        return this.list(wrapper);
    }

    @Override
    public Object getPageList(ObserveInfoPage observeInfoPage) {
        Page<TYwDaObserveInfo> page=new Page<>(observeInfoPage.getPage().getPageNum(),observeInfoPage.getPage().getPageSize());
        QueryWrapper<TYwDaObserveInfo> wrapper = Wrappers.query();
        //组装查询条件
        this.appendWrapper(wrapper,observeInfoPage.getObserveInfo());

        wrapper.orderByAsc(" BASE_ID,FIELD_ID,SORT_NO ");
        //list
        IPage<TYwDaObserveInfo> returnPage = this.page(page, wrapper);
        //总数
        returnPage.setTotal(this.count(wrapper));
        return returnPage;
    }

    @Override
    public String previewYwFile(HttpServletRequest request, HttpServletResponse response, String typicalUrl) throws IOException {
        InputStream inputStream = new FileInputStream(typicalUrl);
        String fileName = typicalUrl.substring(typicalUrl.lastIndexOf("/")+1);
        DownloadUtils.downloadFileForView(request, response, inputStream, fileName);

        return null;
    }

    @Override
    public String dowloadYwFile(HttpServletRequest request, HttpServletResponse response, String typicalUrl,String fileName) throws IOException {
        InputStream inputStream = new FileInputStream(typicalUrl);
//        String fileName = typicalUrl.substring(typicalUrl.lastIndexOf("/")+1);
        DownloadUtils.downloadFile(request, response, inputStream, fileName);

        return null;
    }

    @Override
    public String uploadYwFile(MultipartFile file) throws IOException {
        String uuid = UUID.randomUUID().toString();
        String fileName = uuid + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
        String filePath = downloadTemplateUrlPath + "/observeInfo/"
                + uuid.substring(0,2) + "/" + uuid.substring(0,4);
        File tempFile = new File(filePath);
        if(!tempFile.exists()){
            try {
                tempFile.mkdirs();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        filePath = filePath+"/"+fileName;
        File uploadFile = new File(filePath);
        if(!uploadFile.exists()){
            try {
                uploadFile.createNewFile();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 上传
        UploadUtils.inputstreamtofile(file.getInputStream(),uploadFile);

        return filePath;
    }

    @Override
    public String export(String userId, HttpServletRequest request, HttpServletResponse response) {
        ObserveInfoDto info = new ObserveInfoDto();
        info.setUserId(userId);
        QueryWrapper<TYwDaObserveInfo> wrapper = Wrappers.query();
        //组装查询条件
        this.appendWrapper(wrapper,info);
        wrapper.orderByAsc(" BASE_ID,FIELD_ID,SORT_NO ");
        List<TYwDaObserveInfo> list =  this.list(wrapper);
        Iterator it=list.iterator();
        ByteArrayOutputStream baos=null;
        try{
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            String s = sdf.format(new Date());
            XSSFWorkbook workbook = new XSSFWorkbook();
            XSSFSheet sheet = workbook.createSheet("观测信息列表");
            XSSFRow row = sheet.createRow((short) 0);
            XSSFCell cell = null;
            cell = row.createCell((short) 0);
            cell.setCellValue("序号");
            cell = row.createCell((short) 1);
            cell.setCellValue("观测名称");
            sheet.setColumnWidth(1, 25*256);
            cell = row.createCell((short) 2);
            cell.setCellValue("所属田地");
            sheet.setColumnWidth(2, 25*256);
            cell = row.createCell((short) 3);
            cell.setCellValue("所属基地");
            sheet.setColumnWidth(3, 25*256);
            cell = row.createCell((short) 4);
            cell.setCellValue("观测日期");
            sheet.setColumnWidth(4, 25*256);
            cell = row.createCell((short) 5);
            cell.setCellValue("生育时期");
            sheet.setColumnWidth(5, 25*256);
            cell = row.createCell((short) 6);
            cell.setCellValue("同类占比");
            sheet.setColumnWidth(6, 25*256);
            cell = row.createCell((short) 7);
            cell.setCellValue("主茎叶龄");
            sheet.setColumnWidth(7, 25*256);
            cell = row.createCell((short) 8);
            cell.setCellValue("单株一级分糵");
            sheet.setColumnWidth(8, 25*256);
            cell = row.createCell((short) 9);
            cell.setCellValue("茎糵数");
            sheet.setColumnWidth(9, 25*256);
            cell = row.createCell((short) 10);
            cell.setCellValue("单株次生根条数");
            sheet.setColumnWidth(10, 25*256);
            cell = row.createCell((short) 11);
            cell.setCellValue("苗情分类");
            sheet.setColumnWidth(11, 25*256);
            cell = row.createCell((short) 12);
            cell.setCellValue("施肥情况");
            sheet.setColumnWidth(12, 25*256);
            cell = row.createCell((short) 13);
            cell.setCellValue("病害");
            sheet.setColumnWidth(13, 25*256);
            cell = row.createCell((short) 14);
            cell.setCellValue("虫害");
            sheet.setColumnWidth(14, 25*256);
            cell = row.createCell((short) 15);
            cell.setCellValue("其他灾害");
            sheet.setColumnWidth(15, 25*256);
            cell = row.createCell((short) 16);
            cell.setCellValue("亩穗数");
            sheet.setColumnWidth(16, 25*256);
            cell = row.createCell((short) 17);
            cell.setCellValue("穗粒数");
            sheet.setColumnWidth(17, 25*256);
            cell = row.createCell((short) 18);
            cell.setCellValue("千粒重");
            sheet.setColumnWidth(18, 25*256);
            cell = row.createCell((short) 19);
            cell.setCellValue("亩产量");
            sheet.setColumnWidth(19, 25*256);

            int i=0;
            while(it.hasNext()){
                TYwDaObserveInfo detailInfo=(TYwDaObserveInfo)it.next();

                row=sheet.createRow((int)i+1);
                row.createCell((short) 0).setCellValue(i + 1);
                this.setCellValue(row,1,detailInfo.getObserveName());
                this.setCellValue(row,2,detailInfo.getFieldName());
                this.setCellValue(row,3,detailInfo.getBaseName());
                this.setCellValue(row,4,
                        null != detailInfo.getObserveDate()?String.valueOf(detailInfo.getObserveDate()):"");
                this.setCellValue(row,5,detailInfo.getGrowthPeriod());
                this.setCellValue(row,6,detailInfo.getSameProportion());
                this.setCellValue(row,7,detailInfo.getMainStemLeafAge());
                this.setCellValue(row,8,detailInfo.getIndividualLevel());
                this.setCellValue(row,9,detailInfo.getStemsNumber());
                this.setCellValue(row,10,detailInfo.getSinglePlantDefectiveNumber());
                this.setCellValue(row,11,detailInfo.getSeedCaseClassification());
                this.setCellValue(row,12,detailInfo.getFertilizationConditions());
                this.setCellValue(row,13,detailInfo.getDisease());
                this.setCellValue(row,14,detailInfo.getInsectPests());
                this.setCellValue(row,15,detailInfo.getOtherDisasters());
                this.setCellValue(row,16,detailInfo.getSeedlingEar());
                this.setCellValue(row,17,detailInfo.getPanicleGrain());
                this.setCellValue(row,18,detailInfo.getThousandGrainWeigint());
                this.setCellValue(row,19,detailInfo.getAreaYield());
                i++;
            }
            String filename = "观测信息列表" + s + ".xlsx";
            baos = new ByteArrayOutputStream();
            workbook.write(baos);
            byte[] getData = baos.toByteArray();
            baos.write(getData);
            if(getData.length != 0){
                response.setCharacterEncoding("utf-8");
                response.setContentType("application/x-msdownload;charset=utf-8");
                response.setContentLength(getData.length);
                response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename,"UTF-8"));
                response.getOutputStream().write(getData,0,getData.length);
            }else{
                response.setHeader("MsgError","404");
            }
            response.getOutputStream().flush();
            response.getOutputStream().close();

        }
        catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(null != baos){
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

    private void setCellValue(XSSFRow row, int i, String value) {
        row.createCell((short) i).setCellValue(value==null?"":value);
    }

    private void appendWrapper(QueryWrapper<TYwDaObserveInfo> wrapper, ObserveInfoDto observeInfo) {
        if(StringUtils.isNotEmpty(observeInfo.getId())){
            wrapper.eq("ID",Integer.parseInt(observeInfo.getId()));
        }
        if(StringUtils.isNotEmpty(observeInfo.getObserveCode())){
            wrapper.eq("OBSERVE_CODE",observeInfo.getObserveCode());
        }
        if(StringUtils.isNotEmpty(observeInfo.getObserveName())){
            wrapper.like("OBSERVE_NAME",observeInfo.getObserveName());
        }
        if(StringUtils.isNotEmpty(observeInfo.getFieldId())){
            wrapper.eq("FIELD_ID",Integer.parseInt(observeInfo.getFieldId()));
        }
        if(StringUtils.isNotEmpty(observeInfo.getFieldCode())){
            wrapper.eq("FIELD_CODE",observeInfo.getFieldCode());
        }
        if(StringUtils.isNotEmpty(observeInfo.getFieldName())){
            wrapper.like("FIELD_NAME",observeInfo.getFieldName());
        }
        if(StringUtils.isNotEmpty(observeInfo.getCreateUserId())){
            wrapper.eq("CREATE_USER_ID",observeInfo.getCreateUserId());
        }
        if(StringUtils.isNotEmpty(observeInfo.getBaseId())){
            wrapper.eq("BASE_ID",observeInfo.getBaseId());
        }
        if(StringUtils.isNotEmpty(observeInfo.getBaseName())){
            wrapper.like("BASE_NAME",observeInfo.getBaseName());
        }
        if(StringUtils.isNotEmpty(observeInfo.getUserId())){
            UserLoginInfo userLoginInfo = (UserLoginInfo)redisUtils.get(RedisConstants.USER_INFO_EXPIRE.getKey()+observeInfo.getUserId());
            if(!"admin".equals(userLoginInfo.getUserDto().getLoginName())){
                Set<String> rolesSet =new HashSet<>(
                        userLoginInfo.getRoleDtoList().stream().map(RoleDto::getId).collect(Collectors.toList())
                );
                if(!rolesSet.contains(baseAllPermissionsRoleId)){
                    wrapper.eq("BASE_ID",userLoginInfo.getUserDto().getBaseId());
                }
            }
        }
    }


}
